package com.xht.authorization.server.config;

import com.xht.constant.SecurityConstant;
import com.xht.security.config.annotation.web.configurers.FormLoginConfigurer;
import com.xht.security.web.authentication.XhtAuthenticationSuccessHandler;
import com.xht.utils.Oauth2ConfigUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.SecurityFilterChain;

/**
 * @author Joe Grandja
 * @since 0.0.1
 */
@Slf4j
@Configuration
@RequiredArgsConstructor
public class AuthorizationServerConfig {

    //用于管理新客户和现有客户的RegisteredClientRepository
    private final OAuth2AuthorizationService authorizationService;

    //用于管理新的和现有的授权
    private final RegisteredClientRepository registeredClientRepository;

    //用于管理新的和现有的授权许可
    private final OAuth2AuthorizationConsentService authorizationConsentService;


    /**
     * OAuth2AuthorizationServerConfigurer提供完全自定义 OAuth2 授权服务器的安全配置的能力。它允许您指定要使用的核心组件 -
     * 例如，RegisteredClientRepository、 OAuth2AuthorizationService、OAuth2TokenGenerator和其他。
     * 此外，它还允许您自定义协议端点的请求处理逻辑——
     * 例如，授权端点、令牌端点、令牌内省端点等。<br/>
     * <a href="https://docs.spring.io/spring-authorization-server/docs/0.4.2/reference/html/protocol-endpoints.html#oauth2-token-introspection-endpoint">具体配置请查看</a>
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
        log.info("加载客户端RegisteredClientRepository: {}", registeredClientRepository.getClass());
        log.info("加载授权管理OAuth2AuthorizationService: {}", authorizationService.getClass());
        log.info("加载授权许可管理OAuth2AuthorizationConsentService: {}", authorizationConsentService.getClass());
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
        OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = http.getConfigurer(OAuth2AuthorizationServerConfigurer.class);
        http.apply(authorizationServerConfigurer);
        // 用于管理新客户和现有客户的RegisteredClientRepository（必需）
        authorizationServerConfigurer.registeredClientRepository(registeredClientRepository);
        // 用于管理新的和现有的授权。
        authorizationServerConfigurer.authorizationService(authorizationService);
        // 用于管理新的和现有的授权许可
        authorizationServerConfigurer.authorizationConsentService(authorizationConsentService);
        // 用于自定义 OAuth2 授权服务器配置设置的AuthorizationServerSettings（必需）
        authorizationServerConfigurer.authorizationServerSettings(AuthorizationServerSettings.builder().issuer("http://127.0.0.1:9001").build());
        // 用于生成 OAuth2 授权服务器支持的令牌
        authorizationServerConfigurer.tokenGenerator(Oauth2ConfigUtils.oAuth2TokenGenerator());
        // OAuth2 客户端身份验证的配置器
        authorizationServerConfigurer.clientAuthentication(clientAuthentication -> {
        });
        // OAuth2 授权端点的配置器 允许您自定义 OAuth2 授权请求的预处理、主处理和后处理逻辑
        authorizationServerConfigurer.authorizationEndpoint(authorizationEndpoint -> {
            authorizationEndpoint.consentPage(SecurityConstant.CONSENT_PAGE_URL); // 授权页面
        });
        // OAuth2 令牌端点的配置器 允许您自定义 OAuth2 访问令牌请求的预处理、主处理和后处理逻辑。
        authorizationServerConfigurer.tokenEndpoint(tokenEndpoint -> {
            tokenEndpoint.accessTokenRequestConverter(Oauth2ConfigUtils.accessTokenRequestConverters());
            tokenEndpoint.accessTokenResponseHandler(new XhtAuthenticationSuccessHandler());
        });
        // OAuth2 令牌侦测端点的配置程序。
        authorizationServerConfigurer.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint -> {
        });
        //OAuth2 令牌注销端点的配置器。
        authorizationServerConfigurer.tokenRevocationEndpoint(tokenRevocationEndpoint -> {
        });
        // OAuth2 授权服务器元数据端点的配置器。
        authorizationServerConfigurer.authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> {
        });
        authorizationServerConfigurer.oidc(oidc -> oidc
                // OpenID Connect 1.0 提供者配置端点的配置器。
                .providerConfigurationEndpoint(providerConfigurationEndpoint -> {
                })
                // OpenID Connect 1.0 UserInfo 端点的配置器。
                .userInfoEndpoint(userInfoEndpoint -> {
                })
                // OpenID Connect 1.0 客户端注册端点的配置器。
                .clientRegistrationEndpoint(clientRegistrationEndpoint -> {
                })
        );
        DefaultSecurityFilterChain build = authorizationServerConfigurer.and().apply(new FormLoginConfigurer()).and().build();
        Oauth2ConfigUtils.addCustomDefaultProviders(http);
        return build;
    }

}
